/*
 * 文件名：ContextManager.java
 * 版权：Copyright 2006-2011 AsiaInfo Tech. Co. Ltd. All Rights Reserved. 
 * 描述： ContextManager.java
 * 修改人：齐鹏飞
 * 修改时间：2011-8-26
 * 修改内容：新增
 */
package com.fengxing.ams.web.common;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.stereotype.Component;

import com.fengxing.ams.pub.dto.PubInfoDTO;
import com.fengxing.ams.pub.vo.LogVO;
import com.fengxing.ams.pub.vo.RequestVO;
import com.fengxing.ams.web.facade.mouble.college.CollegeVO;
import com.fengxing.ams.web.facade.mouble.user.UserVO;

/**
 * CTMS 上下文管理者
 * <p>
 * CTMS 上下文管理者====1.请求RequestVO对应的接口编码
 * <p>
 * 
 * <pre>
 * </pre>
 * 
 * @author 齐鹏飞
 * @version CTMS V100R001 2011-8-26
 * @since CTMS V100R001C01
 */
@Component
public class ContextManager implements IContextManager {

	/**
	 * LogID
	 */
	private static final ThreadLocal<String> REQUEST_ID = new ThreadLocal<String>();

	/**
	 * 当前请求JsonObject对象
	 */
	private static final ThreadLocal<PubInfoDTO> PUBINFO = new ThreadLocal<PubInfoDTO>();
	
	
	/**
	 * 当前请求IP
	 */
	private static final ThreadLocal<String> HOST = new ThreadLocal<String>();
	
	/**
	 * 设置当前话单对象
	 */
	private static final ThreadLocal<LogVO> CDR = new ThreadLocal<LogVO>() {
		protected LogVO initialValue() {
			return new LogVO();
		}
	};
	
	private static final Map<Integer, CollegeVO> COLLEGE_CACHE = new HashMap<Integer, CollegeVO> ();
	
	private static final Map<Integer, String> COLLEGEMAP_CACHE = new HashMap<Integer, String> ();

	/**
	 * 请求信息
	 */
	private static final ThreadLocal<RequestVO> REQUEST_INFO = new ThreadLocal<RequestVO>() {
		protected RequestVO initialValue() {
			return new RequestVO();
		}
	};
	
	private static final ThreadLocal<UserVO> USER_CONTEXT = new ThreadLocal<UserVO>() {
		protected UserVO initialValue() {
			return null;
		}
	};

	private static final ThreadLocal<Map<String, String[]>> REQUEST_PARAMETERS = new ThreadLocal<Map<String, String[]>>();

	private ServletContext servletContext;
	
	@Autowired
	private PropertiesFactoryBean messages;

	/**
	 * {@inheritDoc}
	 */
	public void setRequestID(String requestID) {
		REQUEST_ID.set(requestID);
	}

	/**
	 * {@inheritDoc}
	 */
	public String getRequestID() {
		return REQUEST_ID.get();
	}

	/**
	 * {@inheritDoc}
	 */
	public void desctory() {
		REQUEST_ID.remove();
		HOST.remove();
		CDR.remove();
		REQUEST_INFO.remove();
		PUBINFO.remove();
		REQUEST_PARAMETERS.remove();
		USER_CONTEXT.remove();
	}

	/**
	 * {@inheritDoc}
	 */
	public LogVO getCdrVO() {
		return CDR.get();
	}

	/**
	 * {@inheritDoc}
	 */
	public RequestVO getRequestInfo() {
		return REQUEST_INFO.get();
	}

	/**
	 * {@inheritDoc}
	 */
	public ServletContext getServletContext() {
		return this.servletContext;
	}

	/**
	 * 获取servletContext
	 * 
	 * @param servletContext
	 *            要设置的servletContext
	 */
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	public void setPubInfo(PubInfoDTO pubInfo) {
		PUBINFO.set(pubInfo);
	}

	@Override
	public void setRequestParameters(Map<String, String[]> parameterMap) {
		REQUEST_PARAMETERS.set(parameterMap);
	}

	@Override
	public Map<String, String[]> getRequestParameters() {
		return REQUEST_PARAMETERS.get();
	}

	@Override
	public PubInfoDTO getPubInfo() {
		PubInfoDTO pubInfo = PUBINFO.get();
		if (pubInfo == null)
			pubInfo = new PubInfoDTO();
		return pubInfo;
	}

	@Override
	public void setHost(String host) {
		HOST.set(host);		
	}

	@Override
	public String getHost() {
		return HOST.get();
	}

	@Override
	public String getMessage(String key) {
		try {
			return messages.getObject().getProperty(key, key);
		} catch (IOException e) {
		}
		return key;
	}

	@Override
	public void putCollege(Integer college_id, CollegeVO me) {
		COLLEGE_CACHE.put(college_id, me);
	}

	@Override
	public CollegeVO getCollegeVO(Integer college_id) {
		return COLLEGE_CACHE.get(college_id);
	}

	@Override
	public String getCollegeCode(Integer college_id) {
		return COLLEGEMAP_CACHE.get(college_id);
	}

	@Override
	public void putCollegeIdCollegeCodeMap(Object object, Object object2) {
		if (COLLEGEMAP_CACHE.containsKey(object)) {
			String college_code = (String) object2;
			if (!college_code.startsWith("L")) {
				COLLEGEMAP_CACHE.put((Integer)object, college_code);
			}
		} else {
			COLLEGEMAP_CACHE.put((Integer)object, (String)object2);
		}
		
	}
	
	private static final Map<String, SessionEntity> sessionMap = new HashMap<String, SessionEntity> ();
	private static final Lock sessionLock = new ReentrantLock();
	@Override
	public void createSession(UserVO userVO) {
		sessionLock.lock();
		try {
			//通过token，将userVO和session最后一次触发时间关联起来
			sessionMap.put(userVO.getSubject(), new SessionEntity(userVO));
		} finally {
			sessionLock.unlock();
		}
		
	}
	
	
	
	private class SessionEntity {
		UserVO userVO;
		String token;
		long lastAccessTime;
		long lastNotificationTime;
		long lastLoginTime;
		
		public long getLastLoginTime() {
			return lastLoginTime;
		}
		public long getLastNotificationTime() {
			return lastNotificationTime;
		}
		public void setLastNotificationTime(long lastNotificationTime) {
			this.lastNotificationTime = lastNotificationTime;
		}
		SessionEntity(UserVO userVO) {
			this.userVO = userVO;
			this.token = userVO.getSubject();
			this.lastAccessTime = System.currentTimeMillis();
			this.lastLoginTime = System.currentTimeMillis();
		}
		public UserVO getUserVO() {
			return userVO;
		}
		public void setUserVO(UserVO userVO) {
			this.userVO = userVO;
		}
		public String getToken() {
			return token;
		}
		public void setToken(String token) {
			this.token = token;
		}
		public long getLastAccessTime() {
			return lastAccessTime;
		}
		public void setLastAccessTime(long lastAccessTime) {
			this.lastAccessTime = lastAccessTime;
		}
		
	}



	@Override
	public UserVO getSession(String token) {
		
		sessionLock.lock();
		try {
			if (sessionMap.containsKey(token)) {
				SessionEntity sessionEntity = sessionMap.get(token);
				//十分钟的过期时间
				if (System.currentTimeMillis() - sessionEntity.lastAccessTime < 10 * 60 * 1000) {
					sessionEntity.setLastAccessTime(System.currentTimeMillis());
					return sessionEntity.userVO;
				} else {
					//过期清除会话
					sessionMap.remove(token);
				}
			}
			return null;
		} finally {
			sessionLock.unlock();
		}
	}

	@Override
	public void setUserVO(UserVO userVO) {
		USER_CONTEXT.set(userVO);
	}

	@Override
	public UserVO getUserVO() {
		return USER_CONTEXT.get();
	}

	@Override
	public void deleteSession(UserVO userVO) {
		sessionLock.lock();
		try {
			sessionMap.remove(userVO.getSubject());
		} finally {
			sessionLock.unlock();
		}
		
	}

	@Override
	public void clearSession() {
		sessionLock.lock();
		List<String> removing = new ArrayList<String> ();
		try {
			Iterator<Entry<String, SessionEntity>> iter = sessionMap.entrySet().iterator();
			while (iter.hasNext()) {
				Entry<String, SessionEntity> me = iter.next();
				SessionEntity entity = me.getValue();
				if (System.currentTimeMillis() - entity.lastAccessTime > 10 * 60 * 1000) {
					removing.add(me.getKey());
				}
			}
			for (String expiredToken : removing) {
				sessionMap.remove(expiredToken);
			}
		} finally {
			sessionLock.unlock();
		}
	}
	
	private static UserVO SUPPER_MANAGER_USER = null;

	@Override
	public UserVO getSupperManagerUserVO() {
		return SUPPER_MANAGER_USER;
	}

	@Override
	public UserVO getManagerUserVO(Integer collegeId) {
		return MANAGER_USER.get(collegeId);
	}
	
	private static final Map<Integer, UserVO> MANAGER_USER = new HashMap<Integer, UserVO> ();

	@Override
	public void setAllManagerUser(List<UserVO> users) {
		for (UserVO userVO : users) {
			MANAGER_USER.put(userVO.getCollegeId(), userVO);
		}
	}

	@Override
	public void setSupperManagerUser(UserVO userVO) {
		SUPPER_MANAGER_USER = userVO;
	}
	
	private static final ThreadLocal<SessionEntity> SESSION_CONTEXT = new ThreadLocal<SessionEntity>() {
		protected SessionEntity initialValue() {
			return null;
		}
	};
	
	@Override
	public Long getLastQueryNoficationTime() {
		SessionEntity entity = SESSION_CONTEXT.get();
		if (entity.getLastNotificationTime() == 0L) {
			return entity.getLastLoginTime();
		} else {
			return entity.getLastNotificationTime();
		}
	}

	@Override
	public void setSessionEntity(String tokenParam) {
		sessionLock.lock();
		try {
			SessionEntity sessionEntity = sessionMap.get(tokenParam);
			SESSION_CONTEXT.set(sessionEntity);
		} finally {
			sessionLock.unlock();
		}
	}

	@Override
	public void setLastQueryNotificationTime() {
		SessionEntity entity = SESSION_CONTEXT.get();
		entity.setLastNotificationTime(System.currentTimeMillis());
	}

}
